#include "FLOW_core/flow_core_pch.h"
#include "FLOW_core/ILogger.h"
#include "FLOW_core/LogMgr.h"


#include <cstdarg>

namespace CORE
{

	//=============================================================================

	CLogMgr* CLogMgr::sg_p_log_mgr = NULL;

	//=============================================================================

	CLogMgr::CLogMgr( )
	: m_b_initialized( false )
	, m_b_destroyed( false )
	{
	}

	//=============================================================================

	CLogMgr::~CLogMgr( )
	{
		Shutdown( );
	}

	//=============================================================================

	bool_t CLogMgr::Initialize( void )
	{
#ifndef _FINAL
		if( m_b_initialized || m_b_destroyed )
			return false;

		m_b_initialized = true;
#endif
		return true;

	}

	//=============================================================================

	bool_t CLogMgr::Shutdown( void )
	{
#ifndef _FINAL
		if( !m_b_initialized || m_b_destroyed )
			return false;

		m_b_initialized = false;
		m_b_destroyed = true;

		m_v_logger.clear( );
#endif
		return true;
	}

	//=============================================================================

	CLogMgr* CLogMgr::GetInstance( void )
	{
		if( sg_p_log_mgr == NULL )
			sg_p_log_mgr = new CLogMgr( );

		return sg_p_log_mgr;
	}

	//=============================================================================

	bool_t CLogMgr::RegisterLogger( ILogger* ap_logger )
	{
#ifndef _FINAL
		if( !ap_logger || m_b_destroyed )
			return false;

		m_v_logger.push_back( ap_logger );
#endif
		return true;
	}

	//=============================================================================

	bool_t CLogMgr::UnregisterLogger( ILogger* ap_logger )
	{
#ifndef _FINAL
		if( !ap_logger || m_b_destroyed )
			return false;

		CVector< ILogger* >::iterator it = m_v_logger.begin( );
		CVector< ILogger* >::iterator end = m_v_logger.end( );

		for( ; it != end; ++it )
		{
			if( (*it) == ap_logger )
			{
				m_v_logger.erase( it );
				return true;
			}
		}
#endif

		return false; //logger not found
	}

	//=============================================================================

	bool_t CLogMgr::OutputLogMsg( LOG_TYPE ae_log_type, const char_t* apsz_subsystem, const char_t* apsz_log_msg, ... )
	{
#ifndef _FINAL
		if( !m_b_initialized || m_b_destroyed ) //Log Manager is not ready
			return false;

		char_t p_msg_buffer[ 1024 ];
		va_list msg_args;

		va_start( msg_args, apsz_log_msg );
		vsnprintf( p_msg_buffer, 1024, apsz_log_msg, msg_args );
		va_end( msg_args );


		//Once we have the formatted message send it to the loggers
		return OutputLogMsgToLoggers( ae_log_type, apsz_subsystem, p_msg_buffer );
#else
		return true;
#endif
	}

	//=============================================================================

	bool_t CLogMgr::OutputLogMsgToLoggers( LOG_TYPE ae_log_type, const char_t* apsz_subsystem, const char_t* apsz_log_msg )
	{
#ifndef _FINAL
		if( !m_b_initialized || m_b_destroyed ) //Log Manager is not ready
			return false;

		CVector< ILogger* >::iterator it = m_v_logger.begin( );
		CVector< ILogger* >::iterator end = m_v_logger.end( );

		bool_t b_ok = true;

		for( ; it != end; ++it )
			b_ok = b_ok && (*it)->OutputLogMsg( ae_log_type, apsz_subsystem, apsz_log_msg );

		return b_ok;
#else
		return true;
#endif
	}

	//=============================================================================

	void CLogMgr::FormatMsg( LOG_TYPE ae_log_type, const char_t* apsz_subsystem, const char_t* apsz_log_msg, CString& ar_str_log_msg )
	{
#ifndef _FINAL
		const char_t* psz_log_type_name = GetLogTypeName( ae_log_type );

		ar_str_log_msg = "";
		ar_str_log_msg += psz_log_type_name;
		ar_str_log_msg += " - ";
		if( SzCheck( apsz_subsystem ) )
			ar_str_log_msg += apsz_subsystem;
		else
			ar_str_log_msg += "UNDEFINED";
		ar_str_log_msg += " - ";

		if( SzCheck( apsz_log_msg ) )
			ar_str_log_msg += apsz_log_msg;

		ar_str_log_msg += "\n";
#endif
	}

	//=============================================================================

} //namespace CORE